package com.jplus.framework.ioc;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jplus.framework.bean.BeanHandle;
import com.jplus.framework.bean.annotation.Component;
import com.jplus.framework.core.ConfigHandle;
import com.jplus.framework.core.fault.InitializationError;
import com.jplus.framework.ioc.annotation.Autowired;
import com.jplus.framework.ioc.annotation.Value;
import com.jplus.framework.mvc.annotation.Service;
import com.jplus.framework.util.ClassUtil;

/**
 * IocHandle
 * 
 * @author Yuanqy
 *
 */
public class IocHandle {
	private static final Logger log = LoggerFactory.getLogger(IocHandle.class);
	static {
		try {
			Set<Class<?>> beanSet = BeanHandle.beanSet;
			for (Class<?> cla : beanSet) {
				getnewInstance(cla, "", beanSet);
			}
		} catch (Exception e) {
			log.error("IOC注入失败：", e);
			throw new InitializationError(e);
		}
	}

	/**
	 * 实例化类
	 */
	public static Object getnewInstance(Class<?> cla, String name, Set<Class<?>> beanSet) throws Exception {
		Object bean = BeanHandle.getBean(cla);
		if (bean == null) {
			if (cla.isInterface()) {
				bean = findImpl(cla, name, beanSet);
			} else {
				bean = BeanHandle.getTempBean(cla);
				if (bean == null) {
					if (!beanSet.contains(cla))
						return null;
					else {
						bean = cla.newInstance();
					}
				}
			}
		} else {
			return bean;
		}
		Field[] fs = cla.getDeclaredFields();
		for (Field f : fs) {
			f.setAccessible(true);
			// =============获取带有@Autowired的对象
			Autowired reso = f.getAnnotation(Autowired.class);
			if (reso != null) {
				f.set(bean, getnewInstance(f.getType(), reso.value(), beanSet));
			}
			// ==============获取带有@Value的字段
			Value hcv = f.getAnnotation(Value.class);
			if (hcv != null) {
				f.set(bean, ConfigHandle.getString(hcv.value()));
			}
			// ============所有继承@Component注解的注解字段
			Annotation[] ans = f.getAnnotations();
			if (ans != null) {
				for (Annotation a : ans) {
					if (ClassUtil.ckPresentAnno(a.annotationType(), Component.class, true)) {
						f.set(bean, BeanHandle.getBean(a, f.getType()));
						break;
					}
				}
			}

			// // ==============调用观察者[感觉很鸡肋，先删掉]
			// if (watchBo) {
			// IocWatched iocwd = IocWatched.getIocWatchedInstance();
			// if (iocwd.getIocWatcherSize() == 0)
			// watchBo = false;
			// for (IocWatcher iocw : iocwd.getIocWatcher()) {
			// iocw.doIoc(bean, f, beanSet);
			// }
			// }
		}
		if (!cla.isInterface()) {
			log.info("\t[ioc]{}", cla);
			BeanHandle.setBean(cla, bean);
		}
		return bean;
	}

	private static Object findImpl(Class<?> cla, String name, Set<Class<?>> beanSet) throws Exception {
		try {
			for (Class<?> cs : beanSet) {
				if (cla.isAssignableFrom(cs)) {
					Service ser = cs.getAnnotation(Service.class);
					if (ser != null && name.equals(ser.value()))
						return getnewInstance(cs, name, beanSet);
				}
			}
		} catch (Exception e) {
			log.error("class:{};name:{}", cla.getName(), name);
			throw e;
		}
		throw new InitializationError("[IOC]Autowired faild： " + cla.toString() + "(" + name + ")");
	}
}
